home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / basic / vol_inf.exe / FVOLAB.ASM < prev    next >
Encoding:
Assembly Source File  |  1993-05-02  |  27.8 KB  |  757 lines

  1. ; created 02/13/92
  2. ; updated 12/21/92
  3. ;   revised 04/21/93 GETVOL$ 
  4. ;       to display Norton Utilities Safe Format volume labels.
  5. ;       NU routine ends a volume label with nulls rather than spaces.
  6. ;   revised 04/22/93 SETVOL
  7. ;    Test if drive is a network drive and quit if it is.
  8. ;   revised 04/27/93 added DOS Ver 3.xx+ version information so could
  9. ;    tell source of error.  FCB functions return AX = 0FFh if drive
  10. ;    is invalid and do not set any critical error.  Only way to tell
  11. ;    if access error or if drive is invalid is to use DOS Ver 3.xx+
  12. ;    Function 59h.
  13. ;   revised 04/30/93 SETVOL
  14. ;       to handle Norton Utilities Safe Format.
  15. ;       NU routine ends a volume label with nulls rather than spaces.
  16. ;       Only function that will delete such a name is FCB function
  17. ;       13h.  However, that function is not safe to use
  18. ;       in DOS Version 2.xx.  DOS Version 2.xx marked deleted volume
  19. ;       label with 00h rather than correct 0E5h which prevented access
  20. ;       to rest of directory list.  Function 13h in MS DOS Version 5.00,
  21. ;    3.30, and COMPAQ DOS version 3.00 does not have this problem.
  22. ;    Also add check of input string for invalid characters
  23.  
  24. ;=======================================================================
  25. ;   Modifications Copyright (C) Copr. 1992, 1993 by Sidney J. Kelly
  26. ;           All Rights Reserved.
  27. ;           Sidney J. Kelly
  28. ;           150 Woodhaven Drive
  29. ;           Pittsburgh, PA 15228
  30. ;           home phone 412-561-0950 (7pm to 9:30pm EST)
  31. ;=======================================================================
  32. ; «RM82»«TS8,16,24,32,40,48»
  33.  
  34. DOSSEG
  35. .MODEL MEDIUM
  36.  
  37. EXTRN B$ASSN:FAR     ;This allows QBASIC to manipulate fixed length string
  38. EXTRN B$STDL:FAR     ;This creates null strings
  39.  
  40. .DATA
  41.     EXTRN  B$STRINGLEN:WORD      ;inside FDATA
  42.     EXTRN  B$STRINGOFF:WORD      ;inside FDATA
  43.     EXTRN  B$TEMPDATA:WORD       ;inside FDATA
  44.     ; this works inside QB as well as in run time version
  45.     EXTRN   __osversion  :word;this holds minor version in highbyte,
  46.                  ;major version in lowbyte
  47. .CODE
  48.  
  49.     Public GETVOL, SETVOL
  50. ; Please do not remove
  51. Copyright       DB    13,10,'Copyright Copr. (C) 1992, 1993 Sidney J. Kelly',13,10
  52. Copyright1      DB    'All Rights Reserved',13,10,26
  53.  
  54. EVEN        ;save space in DGROUP
  55. Old_CE          Label   DWORD
  56.   CE_Off        DW      0       ; to save space in DGROUP
  57.   CE_Seg        DW      0       ; address of previous handler
  58. Old_DTA         Label   DWORD
  59.   DTA_Off       DW      0       ; to save space in DGROUP
  60.   DTA_Seg       DW      0       ; address of previous handler
  61. Last_Error      DW      0       ; store critical error code
  62.  
  63. ; Format of an extended FCB---------------
  64. XFCB    DB      0FFh            ; signal XFCB
  65.     DB      5 Dup(0)        ; reserved DOS stuff
  66.     DB      8               ; volume attribute
  67. Drive   DB      0               ; drive code goes here
  68. FLabel  DB      11 Dup(0)       ; Volume name
  69. FExtra  DB       5 Dup(0)       ; reserved DOS stuff
  70. FNew    DB    11 Dup(0)    ; holding area for renaming
  71. FScrap  DB      15 Dup(0)       ; extra stuff and padding (6) extra
  72. ; Duncan, "Advanced MS DOS Programming" (Microsoft 1988), p366
  73. ; "Microsoft MS-DOS Programmer's Reference Guide" (Microsoft 1991)
  74.  
  75. ;=======================================================================
  76. ; DECLARE FUNCTION GETVOL$(Drive$, DosErr%)
  77. ; T$ = GETVOL$(Drive$, DosErr%)
  78. ; Purpose:
  79. ;     Returns current volume label of Drive$
  80. ; Input:
  81. ;    Drive$ = Drive letter between 'A' to 'Z'.  If out-of-range then
  82. ;        default drive is substituted
  83. ; Output:
  84. ;    T$ = the volume label.  Note that volume labels can contain spaces.
  85. ;    If any error encountered, returns NULL string
  86. ;       DosErr:
  87. ;        0 if no critical error
  88. ;           -1 if FCB error in DOS version 2.xx
  89. ;           -2 if DOS Version 4.xx w/o SHARE
  90. ;     Else
  91. ;    Standard DOS errors from function 59h
  92. ;            18 = Drive has no label
  93. ;        21 = Drive not ready
  94. ; Theory:
  95. ;    FCB's are used because they work under DOS version 2.x and they
  96. ;    report the name without putting a period between the first
  97. ;       8 letters and the last 3 or squeezing out all the spaces.
  98. ;
  99. ; Note:
  100. ;       Under DOS Ver 4.00, if SHARE is not loaded, then will return with
  101. ; a null string to prevent corruption of a large partition by reason of
  102. ; the use of FCBs.  
  103. ;
  104. ; If drive is not valid, returns a null string and an error code.
  105. ;
  106. ; Has own critical error handler.
  107. ;=======================================================================
  108.  
  109. DrvStrg EQU [BP+8]      ; mnemonic for programmer
  110. DosErr    EQU [BP+6]
  111.  
  112. EVEN
  113. GETVOL PROC FAR
  114.     Push    BP
  115.     Mov     BP,SP           ; get access to stack via BP
  116.     Push    SI        ; save index registers
  117.     Push    DI        ; ditto
  118. ;       Mov     AH,30h          ; do a DOS version check
  119. ;       Int     21h
  120.     Mov     AX,__osversion  ; faster than above
  121.     Cmp     AL,4            ; DOS version 4.xx
  122.     Jne     @f              ; not version 4.xx so skip ahead
  123.     Mov     AX,1000h        ; else,  (AL must = 0)
  124.     Int     2Fh             ; see if SHARE installed
  125.     Cmp     AL,0FFh         ; if AL = FFh then it is installed
  126.     Je      @f              ; o.k. to continue
  127.     Mov     CS:[Last_Error],-2   ; report DOS Ver 4.0x w/o SHARE
  128.     Jmp     Short Error     ; else, return null string, error
  129. @@:
  130. ;Install CE Handler, trashes  AX,BX,ES,DX, returns AX = @data
  131.     Call    CE_INSTALL
  132.     Mov     BX,DrvStrg      ; get DRIVE$
  133.     Mov     CX,[BX]         ; get length in CX
  134.     JCXZ    Use_Default     ; if LEN(Drive$) = 0 use default drive
  135.     Mov     BX,[BX+2]       ; get offset of string
  136.     Mov     AL,[BX]         ; get character in AL
  137.     And     AL,0DFh         ; capitalize character
  138.     Sub     AL,'@'          ; make it 1 biased
  139.     Or      AL,AL           ; is it 0?
  140.     Jz      Begin           ; yes, so use default drive
  141.     Cmp     AL,27           ; is it > 26?
  142.     JB      Begin           ; no, so test it
  143. Use_Default:
  144.     Mov    AH,19h        ; else read default drive
  145.     Int    21h        ; into AL (useful for testing)
  146. Begin:
  147.     ; AL must contain desired drive
  148.     Call    Search_4_Name    ; search for current volume name
  149.     ; must preserve DI because will use it below
  150.     Assume  DS:NOTHING, ES:NOTHING  ; tell MASM
  151.     Cmp     AL,0FFh         ; name found?
  152.     Jne     @f              ; yes, so check for CE errors
  153.     Call    GetErrInfo      ; else find out why not found
  154. @@:
  155.     Cmp     CS:[Last_Error],0    ; did DOS give us an error?
  156.     Jne     Error           ; got an error
  157. ; new version
  158. ;    revised 04/21/93 to handle Norton Utilities Safe Format
  159. ;    NU routine ends a volume label with nulls rather than spaces.  While
  160. ;     QBASIC PRINT function can display nul strings, other routines
  161. ;    may trigger errors.
  162.     Mov     CX,11           ; else, search for trailing spaces
  163.     Dec    DI              ; remove 1 char overrun from DI
  164.     Mov    BL,20h        ; look for a space
  165. Search_4_End:
  166.     Mov    AL,ES:[DI]    ; get character
  167.     Cmp    AL,BL        ; is it a space?
  168.     Je    @f        ; yes, jump ahead
  169.     Or    AL,AL        ; is it a nul?
  170.     Jne    Loop_Exit    ; no, have end of label
  171. @@:
  172.     Dec    DI        ; reduce pointer by 1
  173.     Loop    Search_4_End    ; loop CX times
  174. Loop_Exit:
  175.     JCXZ    Error           ; all spaces/nuls if CX = 0
  176. ; copy our string to DGROUP buffer
  177.     Mov     DX,CX           ; save length in DX temporarily
  178.     Mov     SI,OFFSET FLabel ; put source string in DS:SI
  179.     Mov     AX,SS
  180.     Mov     ES,AX
  181. ;       Assume  ES:@data
  182.     Assume  DS:@data        ; lie for a moment
  183.     Mov     DI,OFFSET B$TEMPDATA  ; put destination in ES:DI
  184.     Assume  DS:NOTHING      ; tell the truth again
  185.     Rep     MovsB           ; store all the bytes
  186.     Mov     CX,DX           ; restore CX to original length
  187. CopyString:
  188.   ; Reset CE Handler, trashes AX,DX, returns AX = @data
  189.   ; Note: must preserve CX!
  190.     Call    Clean_Up        ; restore CE and DTA info
  191.     Assume  DS:@data
  192. ; return string to BASIC
  193.     Push    DS              ; Store the Data Segment
  194.     Mov     AX,OFFSET B$TEMPDATA
  195.     Push    AX              ; Store offset of string
  196.     Push    CX              ; Store LEN of string
  197.     Push    DS              ; Store the Data Segment
  198.     Mov     AX,OFFSET B$STRINGLEN
  199.     Push    AX              ; Store Descriptor of string
  200.     Xor     AX,AX           ; tell Basic it is a variable string
  201.     Push    AX              ; Store a 0
  202.     Call    B$ASSN          ; copy string into BASIC space
  203. Finis:
  204.     Mov    BX,DosErr
  205.     Mov     AX,CS:[Last_Error]
  206.     Mov    [BX],AX        ; report back any critical errors
  207.     Mov     AX,OFFSET B$STRINGLEN ; address of descriptor
  208.     Pop     DI              ; restore registers used
  209.     Pop     SI
  210.     Pop     BP
  211.     Ret     4               ; remove 2 parameters from stack
  212. Error:
  213.     Mov     AH,0Dh          ; reset disk because of error
  214.     Int     21h
  215. ; Reset CE handler, trashes AX,DX, returns AX = @data
  216. ; Reset DTA address, preserves CX
  217.     Call    Clean_Up
  218.     Assume  DS:@data        ; point DS to @data
  219. ; return NULL string
  220.     Mov     AX,OFFSET B$STRINGLEN  ; put address of
  221.     Push    AX              ; descriptor in AX
  222.     Call    B$STDL          ; make it a null string
  223.     Xor     AX,AX           ; clear descriptor too
  224.     Mov     B$STRINGLEN,AX  ; needed only for MASM strings
  225.     Mov     B$STRINGOFF,AX
  226.     Jmp     Short Finis
  227. GETVOL ENDP
  228.  
  229.  
  230. ;=======================================================================
  231. ; DECLARE FUNCTION SETVOL%(Drive$, NewName$)
  232. ; T% = SETVOL$(Drive$, NewName$)
  233. ;
  234. ; Theory:
  235. ;    FCB's are used because they work under DOS version 2.x, and they
  236. ;    report the name without putting a period between the first
  237. ;    8 letters and the last 3.  The handle functions work only under
  238. ;       DOS Ver. 3.x+, they do not display the volume name properly.  In
  239. ;       addition, FCB's must be used to change volume names, even with
  240. ;       DOS version 3.x+.
  241. ; Duncan, "Advanced MS DOS Programming" (Microsoft 1988), p175
  242. ;
  243. ; Input:
  244. ;    Drive$ = Drive letter between 'A to Z' if out-of-range then
  245. ;        default drive is substituted
  246. ;    NewName$
  247. ;         If LEN(NewName$) = 0 then
  248. ;               old label will be deleted and no new label will be substituted.
  249. ;
  250. ;       Routine allows use of embedded spaces.  However, other characters
  251. ;       that are not permitted in filenames will cause the routine
  252. ;       to report an error.
  253. ;
  254. ; Returns:
  255. ;       0 = Change Successful
  256. ;      -1 = FCB error in DOS version 2.xx (not used here)
  257. ;      -2 = DOS Version error, Ver 4.0x w/o SHARE
  258. ;      -3 = DOS Version less than 3.xx
  259. ;      -4 = Network Drive, no label possible
  260. ;      -5 = Invalid characters in NewName$ (nothing else happens)
  261. ;     Else
  262. ;    Standard DOS errors from function 59h
  263. ;    21, 83 = Drive not ready
  264. ;     8 = Invalid characters in input string
  265. ;    82 = Directory full
  266. ;
  267. ; Note:
  268. ;       Under DOS Ver 4.0x, if SHARE is not loaded, then will not change
  269. ; Volume label to prevent corruption of a large partition by reason of
  270. ; the use of FCBs.
  271. ;
  272. ; Partly based on a public domain routine by William Cravener (11/14/92)
  273. ;
  274. ; Has own critical error handler.
  275. ;=======================================================================
  276.  
  277. DrvStrg EQU [BP+8]          ; mnemonic for programmer
  278. NewName EQU [BP+6]
  279.  
  280. EVEN
  281. Bad_DOS:
  282.     Mov     CX,-3           ; report DOS version < 3.xx
  283.     Jmp     Finis1          ; quit
  284. EVEN
  285. Error2:                         ; stepping stone
  286.     Jmp     Return_CE_Err
  287. EVEN
  288. DV_Error:            ; report back have DOS Ver 4.00 w/o SHARE
  289.     Mov     CX,-2        ; that version req. SHARE
  290.     Jmp     Finis1        ; or FCB's will damage large disks
  291. EVEN
  292. SETVOL PROC FAR
  293.     Push    BP
  294.     Mov     BP,SP           ; get access to stack via BP
  295.     Push    SI              ; save index registers
  296.     Push    DI              ; ditto
  297.     CLD                     ; to be safe
  298.     Mov    BX,NewName    ; get address of NewName in BX
  299.     Call    CHECK_STRING    ; check for invalid characters
  300.     Jnc    @f        ; all characters valid
  301.     Mov    CX,-5        ; at least 1 character is invalid
  302.     Jmp    Finis1        ; quit with an error
  303. @@:
  304. ;       Mov     AH,30h          ; do a DOS version check
  305. ;       Int     21h
  306.     Mov     AX,__osversion  ; faster than above
  307.     Cmp     AL,2            ; if version < 3.xx, quit
  308.     Je      Bad_DOS
  309.     Cmp     AL,4            ; check if DOS version 4.xx
  310.     Jne     Skip_Share      ; not version 4.xx so skip ahead
  311.     Mov     AX,1000h        ; else,  (AL must = 0)
  312.     Int     2Fh             ; see if SHARE installed
  313.     Cmp     AL,0FFh         ; if AL = FFh then it is installed
  314.     Jne     DV_Error        ; if DOS Ver 4.00 w/o SHARE quit w/ error
  315. Skip_Share:
  316. ; Install CE Handler, trashes  AX,BX,ES,DX, returns AX = @data
  317.     Call    CE_INSTALL
  318.     Mov     BX,DrvStrg      ; get DRIVE$
  319.     Mov     CX,[BX]         ; get length in CX
  320.     JCXZ    Use_Default1    ; if LEN(Drive$) = 0 use default drive
  321.     Mov     BX,[BX+2]       ; get offset of string
  322.     Mov     AL,[BX]         ; get character in AL
  323.     And     AL,0DFh         ; capitalize character
  324.     Sub     AL,'@'          ; make it 1 biased
  325.     Or      AL,AL           ; is it 0?
  326.     Jz      Check_Net    ; yes, so use default drive
  327.     Cmp     AL,27           ; is it > 26?
  328.     JB      Check_Net    ; no, so use it
  329. Use_Default1:
  330.     Mov    AH,19h        ; read default drive
  331.     Int    21h        ; into AL (useful for testing)
  332. Check_Net:            ; see if a network drive
  333.     Push    AX        ; save drive letter in AX
  334.     Mov    BL,AL        ; put drive letter in BL
  335.     Mov    AX,4409h    ; requires DOS version 3.10+
  336.     Xor    DX,DX        ; make sure DX is 0 (for version 3.00)
  337.     Int    21h        ; check if drive is remote/local
  338.     Jc    Read_Current_Vol ; assume not a network if get error
  339.     Pop    AX        ; restore AX
  340.     Test    DH,00010000b    ; see if bit 12 set in DX
  341.     Jz    Read_Current_Vol ; bit clear, drive is local
  342.     Mov    CX,-4        ; report back drive is a network drive
  343.     Jmp    Error1        ; and quit
  344. Read_Current_Vol:            ; see if any previous Vol. name
  345.     ; AL must contain desired drive
  346.     Call    Search_4_Name    ; search for current volume name
  347.     Assume  DS:NOTHING, ES:NOTHING  ; tell MASM
  348.     Cmp     CS:[Last_Error],0    ; did DOS give us an error?
  349.     Jne     Error2          ; got an error, quit (through stepping stone)
  350.     Cmp    AL,0FFh        ; name not found?
  351.     Je    Make_New_Vol    ; yes, so set new one
  352.     ; and ignore all non-CE errors
  353. Delete_Old_Name:
  354.     ;Drive letter already set as well as attribute byte
  355.     ;This section deletes all volume labels using wildcard feature of 
  356.     ; function 13h.  This is the only way  to delete any nul terminated
  357.     ; volume labels such as that created  by Norton's Safe Format.
  358.     ; MS-DOS's Ver 5.00 LABEL.EXE has the same problem with
  359.     ; Norton's Safe Format volume labels but does not use this solution
  360.     ; which is why it can't delete null terminated  volume labels.
  361.     ; However MS-DOS version 3.30 LABEL.COM and COMPAQ version 3.00
  362.     ; LABEL.COM can rename nul terminated volume labels.
  363.     Assume  DS:NOTHING, ES:NOTHING  ; tell MASM
  364.     Mov     DI,OFFSET FLabel ; get address of search buffer
  365.     Mov     AL,'?'          ; load '?' char into AL
  366.     Mov     CX,11           ; set to load 11 "?"'s
  367.     Rep     StosB           ; load FCB (ES:DI) search buffer w/ all "?"
  368.     Xor     AL,AL
  369.     Mov     DI,OFFSET FExtra ; clean out old area
  370.     Mov     CX,31           ; muddied by name search
  371.     Rep     StosB           ; into area pointed by ES:DI
  372.     Mov     DX,OFFSET XFCB  ; point DX to XFCB
  373.     Mov     AH,13h          ; delete old volume name
  374.     Int     21h             ; (unsafe in version 2.xx!!)
  375.     Cmp     AL,0FFh         ; any error?
  376.     Jne     @f              ; no, jump ahead
  377.     Call    GetErrInfo      ; else, get reason for error
  378. @@:
  379.     Cmp     CS:[Last_Error],0 ; read CE/DOS error information
  380.     Jne     Return_CE_Err   ; quit if get such an error
  381. Make_New_Vol:
  382.     Xor    AL,AL
  383.     Mov     DI,OFFSET FExtra ; clean out old area
  384.     Mov     CX,31           ; muddied by name search
  385.     Rep    StosB        ; into area pointed by ES:DI
  386.     Mov     DI,OFFSET FLabel ; get address of search buffer into DI
  387.     Call    Parse_Name    ; Load NewName$ into buffer
  388.     Assume    DS:NOTHING    ; tell MASM DS=CS
  389.     Jc    Ender        ; if LEN(NewName$) = 0 then quit
  390.     Mov    DX,OFFSET XFCB  ; get offset into DX
  391.     Mov    AH,16h        ; create new volume name
  392.     Int    21h        ; set volume to new name
  393.     Cmp     AL,0FFh         ; any error?
  394.     Jne     @f              ; no, jump ahead
  395.     Call    GetErrInfo      ; else, get reason for error
  396. @@:
  397.     Cmp     CS:[Last_Error],0 ; read CE/DOS error information
  398.     Jne     Return_CE_Err   ; quit if get such an error
  399. Close_File:             ; Close file we just created
  400.     Mov    DX,OFFSET XFCB  ; get offset into DX
  401.     Mov    AH,10h        ; close file
  402.     Int    21h        ; ignore all close errors
  403.                 ; but critical errors
  404.     Cmp     CS:[Last_Error],0 ; read CE error information
  405.     Jne    Return_CE_Err    ; quit if get a CE error
  406. Ender:                ; else, 
  407.     ; preserves CX and sets DS = @data
  408.     Call    Clean_Up        ; restore DTA & CE vectors
  409.     Xor     CX,CX           ; report back all o.k.
  410.     Assume  DS:@data
  411. Finis1:
  412.     Mov    AX,CX        ; get result code back from CX
  413.     Pop     DI              ; restore registers used
  414.     Pop     SI
  415.     Pop     BP
  416.     Ret     4               ; remove 2 parameter from stack
  417. Return_CE_Err:
  418.     Mov     CX,CS:[Last_Error]   ; else get critical error in CX
  419. Error1:
  420.     Mov     AH,0Dh          ; reset disk because of error
  421.     Int     21h
  422.     ; preserves CX and sets DS = @data
  423.     Call    Clean_Up    ; restore DTA & CE vectors
  424.     Assume  DS:@data
  425.     Jmp     Short Finis1
  426. SETVOL ENDP
  427.  
  428. ;=======================================================================
  429. ; Installs the CE handler, made a subroutine to save space
  430. ; Trashes  AX,BX,ES,DX, returns AX = @data. ES & DS = @data
  431. ;=======================================================================
  432.  
  433. EVEN
  434. CE_INSTALL  PROC  NEAR
  435.     Assume  DS:NOTHING, ES:NOTHING ; tell MASM only CS & SS defined
  436.     Xor     AX,AX
  437.     Mov     CS:[Last_Error],AX   ; clear last error
  438.     CLI                     ; prevent interruption
  439.     Mov     AX,3524h        ; use DOS to get current
  440.     Int     21h             ; address of the vector
  441.     Mov     CS:[CE_Off],BX  ; address returned in ES:BX
  442.     Mov     CS:[CE_Seg],ES  ; save for removal
  443.     Mov     AX,CS
  444.     Mov     DS,AX           ; set DS = CS
  445.     ;need this so offset is calculated with reference to
  446.     ;CSEG rather than DGROUP
  447.     Assume  DS:NOTHING
  448.     Mov     DX,OFFSET CE    ; get address of our MASM handler
  449.     Mov     AX,2524h        ; tell DOS we're taking this vector
  450.     Int     21h             ; grab the vector
  451.     STI                     ; allow interrupts again
  452.     Mov     AX,SS           ; in QBASIC SS=DGROUP
  453.     Mov     DS,AX
  454.     Assume  DS:@data        ; reset DS = to DGROUP
  455.     Mov     ES,AX           ; Make ES = DGROUP
  456. ;       Assume  ES:@data        ; tell MASM
  457.     Ret
  458. CE_INSTALL  ENDP
  459.  
  460. ;=======================================================================
  461. ;CHECK_STRING
  462. ; Check Input String for Invalid Characters
  463. ; Input:
  464. ;    DS:BX points to input string's descriptor
  465. ; Result:
  466. ;    Sets Carry if input string contains invalid characters
  467. ;    Clears Carry if input string is o.k.
  468. ; Assumes:
  469. ;    CLD
  470. ; Preserves: 
  471. ;    ES,SI,DI
  472. ; Trashes:
  473. ;    AX,BX,CX,DX
  474. ;=======================================================================
  475.  
  476. Invalid_Char db 34,59,9,0   ; quote, semicolon, tab, and nul
  477.          db "*?&^+/,\=[.]<|>(:)"
  478. ; This list is from MS-DOS version 5.00 instruction book,
  479. ; FCB's also will permit you to use "^&()" in a volume label.
  480. Len_IC  EQU  $-Invalid_Char ; calculates length of Invalid_Char string
  481.  
  482. EVEN
  483. CHECK_STRING PROC NEAR
  484.     Assume    ES:NOTHING, DS:@data
  485.     Push    ES        ; save register we will change
  486.     Push    SI
  487.     Push    DI
  488.     Mov     CX,[BX]         ; get length of input string
  489.     Jcxz    CS_OK        ; if zero, quit
  490.     Mov    SI,[BX+2]    ; get offset of string in SI
  491.     Mov    BX,CX        ; store length of input in BX
  492.     Mov    AL,32        ; check for a leading space
  493.     Cmp    AL,Byte Ptr [SI]
  494.     Je    CS_Error    ; a leading space is illegal, quit w/ error
  495.     Mov    AX,CS
  496.     Mov    ES,AX        ; point ES to CS
  497.     Assume    DS:NOTHING    ; lie so offset works
  498.     Mov    DX,OFFSET Invalid_Char ; ES:DX points to Invalid_Char string
  499.     Assume    DS:@data    ; tell truth again
  500. EVEN                ; speed up loop
  501. CS_Check:
  502.     Dec    BX        ; reduce counter
  503.     JS    CS_OK        ; if less than zero, quit, no matches
  504.     LodsB            ; put DS:SI into AL
  505.     Mov    CX,Len_IC    ; put length of check string
  506.     Mov    DI,DX        ; reload offset of comparison string
  507.     Repne     Scasb        ; find first match, loop CX times
  508.     ; as long as AL <> ES:DI, ZF set if match found
  509.     Jz    CS_Error    ; found a match, so note the error
  510.     Jmp    Short CS_Check    ; start loop again
  511. CS_OK:
  512.     CLC
  513. CS_Finis:
  514.     Pop    DI        ; restore registers
  515.     Pop    SI
  516.     Pop    ES
  517.     Ret
  518. CS_Error:
  519.     STC
  520.     Jmp    CS_Finis
  521. CHECK_STRING ENDP
  522.  
  523. ;=======================================================================
  524. ; Search_4_Name
  525. ; Searches for current volume name, if found loads up XFCB with name
  526. ; Input:
  527. ;    Assumes AL has desired drive
  528. ; Returns:
  529. ;    DI pointing 1 byte higher in memory than end of FCB extension area
  530. ;    DS = CS = ES
  531. ;    changes DTA.  AL = 0 if successful, AL = FF if error
  532. ;=======================================================================
  533.  
  534. EVEN
  535. Search_4_Name Proc Near
  536.     Mov     CS:[Drive],AL   ; store drive
  537.     Mov     AH,2Fh          ; get current FCB DTA
  538.     Int     21h
  539.     Mov     CS:[DTA_Off],BX ; save DTA address
  540.     Mov     CS:[DTA_Seg],ES
  541.     Mov     AX,CS
  542.     Mov     DS,AX           ; DS points to SEG of XFCB
  543.     Mov     ES,AX           ; ES points to SEG of XFCB
  544.     Assume  DS:NOTHING, ES:NOTHING  ; tell MASM
  545.     Mov     DI,OFFSET FLabel ; get address of search buffer
  546.     Mov     AL,'?'          ; load '?' char into AL
  547.     Mov     CX,11           ; set to load 11 "?"'s
  548.     Rep     StosB           ; load FCB (ES:DI) search buffer w/ all "?"
  549.     Mov     DX,OFFSET XFCB  ;  put DTA buffer offset into DX
  550.     Mov     AH,1Ah          ; move FCB DTA (DS:DX) to our area
  551.     Int     21h
  552.     Mov    DX,OFFSET XFCB    ; put extended FCB offset in DX
  553.     Mov     AH,11h          ; do Find First search for volume label
  554.     Int     21h        ; volume attribute already fixed
  555.     Ret
  556. Search_4_Name Endp
  557.  
  558. ;=======================================================================
  559. ;Parse_Name
  560. ; Takes NewName$ and puts it into buffer pointed by DI
  561. ; Assumes:
  562. ;    ES = CS, ES:DI contain address of start of destination buffer
  563. ; Changes:
  564. ;    AX,BX,CX,DS,SI,DI
  565. ; Returns:
  566. ;    IF LEN(NewName$) = 0 THEN Carry set
  567. ;
  568. ;    ELSE Carry clear
  569. ;
  570. ;    AX,DS = CS, CX = 0, BX = LEN(NewName$)
  571. ;=======================================================================
  572.  
  573. NewName EQU [BP+6]
  574.  
  575. EVEN
  576. Parse_Name Proc Near
  577.     Mov     BX,DI           ; save incoming offset in BX
  578.     Assume  DS:NOTHING
  579.     Mov     AL,20h          ; load space char into AL
  580.     Mov     CX,11           ; load 11 " "'s
  581.     Rep     Stosb           ; into area pointed by ES:DI
  582.     Mov     DI,BX           ; restore original value from BX
  583.     Mov     AX,SS
  584.     Mov     DS,AX
  585.     Assume  DS:@data        ; get access to stack
  586.     Mov     SI,NewName
  587.     Mov     CX,[SI]         ; get length in CX
  588.     JCXZ    Ender1          ; if LEN(NewName$) = 0 quit w/o error
  589.     Mov     SI,[SI+2]       ; get offset of NewName$ into SI
  590.     Mov     BX,11           ; assume CX > 11 bytes
  591.     Cmp     CX,11           ; is LEN(NewName$) > 11
  592.     Ja      @f              ; yes, so guessed correctly
  593.     Mov     BX,CX           ; no, put actual LEN in BX
  594. @@:
  595.     Mov     CX,BX           ; put min of old CX or 11 in CX
  596.     Rep     Movsb           ; move DS:SI to ES:DI
  597.     CLC            ; clear carry flag
  598.     Mov     AX,CS
  599.     Mov     DS,AX           ; reset DS to above buffer
  600.     Assume  DS:Nothing
  601.     Ret
  602. Ender1:
  603.     Mov    BX,CX        ; put 0 in BX
  604.     Mov     AX,CS
  605.     Mov     DS,AX           ; reset DS to above buffer
  606.     Assume  DS:Nothing
  607.     STC            ; set carry flag
  608.     Ret
  609. Parse_Name ENDP
  610.  
  611. ;=======================================================================
  612. ; Clean_Up
  613. ;     Resets CE handler, restores FCB DTA
  614. ;     Sets AX & DS = @data
  615. ;     Trashes DX.  Saves CX
  616. ;=======================================================================
  617.  
  618. EVEN
  619. Clean_Up PROC NEAR
  620. ; Reset CE handler, trashes AX,DX, returns AX = @data
  621.     LDS     DX,CS:[Old_CE]  ; LDS is fast
  622.     Assume  DS:NOTHING
  623.     Mov     AX,2524h        ; Restore 24h vector
  624.     Int     21h             ; restore it
  625.     LDS     DX,CS:[Old_DTA] ; LDS is fast
  626.     Mov     AH,1Ah          ; Restore DTA area (DS:DX)
  627.     Int     21h
  628.     Mov     AX,SS
  629.     Mov     DS,AX
  630.     Assume  DS:@data        ; point DS to @data
  631.     Ret
  632. Clean_Up ENDP
  633.  
  634. ;=======================================================================
  635. ; GetErrInfo
  636. ;   Purpose:
  637. ;        Gets DOS's reason for FCB access error.  If CE error already
  638. ;    occurred, then CE error used.  This prevents a "drive not ready" error
  639. ;    (Code 21) from being converted into a "fail on interrupt 24h" (Code 83).
  640. ;   Requires:
  641. ;        DOS Version 3.00, returns FCB error of -1 if DOS version 2.xx
  642. ;   Registers:
  643. ;        All but AX and FLAGS are saved
  644. ;=======================================================================
  645.  
  646. EVEN
  647. GetErrInfo PROC NEAR
  648.     Assume  DS:NOTHING, ES:NOTHING, SS:@data
  649.     Mov     AX,SS:[__osversion]  ; check DOS version
  650.     Cmp     AL,2            ; DOS version 2.xx?
  651.     Je    Wrong_Ver    ; quit, this function not supported in Ver 2.xx
  652.     Cmp     CS:[Last_Error],0   ; already have CE error? CS <> 0?
  653.     Jne     GetErrEnd       ; yes, so use it
  654.     Push    BX        ; save all important registers
  655.     Push    CX        ; Function 59h destroys most registers
  656.     Push    DX
  657.     Push    SI
  658.     Push    DI
  659.     Push    BP
  660.     Push    DS
  661.     Push    ES
  662.     Mov     AH,59h        ; call extended error information
  663.     Xor     BX,BX        ; set implementation to 0
  664.     Int     21h
  665.     Mov     CS:[Last_Error],AX      ; store error code from AX
  666.     Pop     ES        ; restore all registers changed
  667.     Pop     DS
  668.     Pop     BP
  669.     Pop     DI
  670.     Pop     SI
  671.     Pop     DX
  672.     Pop     CX
  673.     Pop     BX
  674. GetErrEnd:                ; exit if CE handler already
  675.     Ret                ; got an error
  676. Wrong_Ver:
  677.     Mov     CS:[Last_Error],-1      ; store error code from AX
  678.     Ret
  679. GetErrInfo ENDP
  680.  
  681. ;=======================================================================
  682. ; Substitute critical error handler, does nothing but capture error.
  683. ; We let DOS process error, because that is only way to safely reset
  684. ; DOS's internal critical error flag.
  685. ;
  686. ; List of Critical errors:
  687. ;    19 = Disk write protected
  688. ;    20 = Unknown unit
  689. ;    21 = Drive not ready
  690. ;       22 = Unknown command
  691. ;    23 = CRC error
  692. ;    24 = Bad request structure length
  693. ;    25 = Seek error
  694. ;    26 = Unknown media type
  695. ;    27 = Sector not found
  696. ;    28 = Out of paper
  697. ;    29 = Write fault
  698. ;    30 = Read fault
  699. ;    31 = General failure
  700. ;    32 = Sharing violation
  701. ;    33 = Lock violation
  702. ;    34 = Invalid disk change
  703. ;    35 = FCB unavailable
  704. ;    36 = Sharing buffer overflow
  705. ;=======================================================================
  706.  
  707. EVEN
  708. CE PROC FAR
  709.     Assume  DS:NOTHING, ES:NOTHING ; tell MASM only CS defined
  710.     ;the following CODE returns to DOS for processing
  711.     Add     DI,13h          ; increment error
  712.     And     DI,0FFh         ; clear undefined portion
  713.     Mov     CS:[Last_Error],DI   ; store in CSEG
  714.     Xor     AL,AL           ; tell DOS to ignore error
  715. ; In DOS 3.xx and above, DOS will often turn ignore into fail
  716. ; which is what we want.
  717.     IRET                    ; return & pop flags from stack
  718. CE ENDP
  719. END
  720.  
  721.  
  722. ;-----------------------------old code----------------------
  723.  
  724. ;Rename_Old_Volume:
  725. ; We rename rather than delete using Function 13h because DOS Version 2.xx
  726. ; destroyed  FAT if the volume label were erased.  Rename function did not
  727. ; have that problem. Duncan, "Advanced MS DOS Programming" 
  728. ; (Microsoft 1988), p175
  729. ;
  730. ; Rename DOES NOT permit a change to null terminated volume labels.
  731. ; therefore it was dropped.
  732.         Assume  DS:NOTHING, ES:NOTHING;   tell MASM
  733.         Mov     DI,OFFSET FExtra   ; clear out garbage
  734.         Xor     AL,AL           ; put nul in AL
  735.         Mov     CX,5
  736.         Rep     StosB           ; clean 5 spaces at ES:DI
  737.         Mov     DI,OFFSET FNew  ; address of rename buffer into DI
  738.         Call    Parse_Name      ; Load NewName$ into buffer
  739.         Assume  DS:NOTHING      ; tell MASM DS=CS
  740.         Jnc     Do_Rename       ; if no carry, then rename file
  741. ; else load a default name if LEN(NewName$) = 0
  742.         Mov     DI,OFFSET FNew  ; else, LEN(NewName$) = 0
  743.         Mov     AL,'_'          ; so give a default name of '_________'
  744.         Mov     CX,11
  745.         Rep     Stosb
  746. Do_Rename:
  747.         Mov     DX,OFFSET XFCB  ; point to modified FCB
  748.         Mov     AH,17h          ; rename it
  749.         Int     21h
  750.         Cmp     AL,0FFh         ; any error?
  751.         Jne     @f              ; no, jump ahead
  752.         Call    GetErrInfo      ; else, get reason for error
  753. @@:
  754.         Cmp     CS:[Last_Error],0    ; see if CE or DOS error
  755.         Jne     Return_CE_Err   ; quit w/ CE/DOS error
  756.         Jmp     Close_File      ; else, close file
  757.